/*******************************************************************************
 * Witz - Winboard Chess Engine                                                *
 * PST.C                                                                       *
 *                                                                             *
 * Implements dynamic Piece-Square Tables                                      *
 *                                                                             *
 * Please refer to the licence notice in MAIN.C                                *
 *                                                                             *
 * Copywright (C) 2006 Pradu Kannan                                            *
 * http://witz.sf.net/                                                         *
 ******************************************************************************/

#include "build.h"
#include "defs.h"
#include "protos.h"
#include "data.h"

//Piece Square table [side][piece][square]
int pieceSquare[2][7][64];

/*generatePieceSquare()
 *generates the piece square database
 */
//A temporary piece square for black which is used in generatePieceSquare
const int tempPSQ[64]={
		72,	82,	86,	90,	90,	86,	82,	72,
		22,	32,	36,	40,	40,	36,	32,	22,
		0,	12, 16,	20,	20,	16,	12,	0,
		-7,	-2,	3,	16,	16,	3,	-2,	-7,
		-10,-5,	2,	12,	12,	2,	-5,	-10,
		-9,	-4,	0,	4,	4,	0,	-4,	-9,
		-10,-5,	0,	4,	4,	0,	-5,	-10,
		0,	0,	0,	0,	0,	0,	0,	0
};

/*printPCSQ()
 *a function that prints the pieceSquare
 */
void printPCSQ()
{
	int i,j,piece;

	for(piece=P;piece<NUMPIECETYPES;piece++)
	{
		printf("WHITE %c:\n",pieceToStr[piece]);
		for(i=56;i>=0;i-=8)
		{
			for(j=0;j<8;j++)
			{
				printf("%3d ",pieceSquare[WHITE][piece][i+j]);
			}
			printf("\n");
		}
		printf("BLACK %c:\n",pieceToStr[piece]);
		for(i=56;i>=0;i-=8)
		{
			for(j=0;j<8;j++)
			{
				printf("%3d ",pieceSquare[BLACK][piece][i+j]);
			}
			printf("\n");
		}
		printf("\n");
	}
}

/*generatePieceSquare(board* pos)
 *generates the PieceSquare info dynamically
 *
 *@param pos - the board position to generate pieceSquares for
 */
void generatePieceSquare(board* pos)
{
	int i,j;
	U64 squares, attacks, attacks2;
	char kingpos, target, target2, target3;

	/****************MOBILITY***************/

	//No Piece
	for(i=0;i<2;i++)
		for(j=0;j<64;j++)
			pieceSquare[i][EMPTY][j]=0;

	//Pieces
	for(i=0;i<2;i++)
		for(j=0;j<64;j++)
			pieceSquare[i][N][j]=MOB_WEIGHT*popCount(Nmoves(*pos,j))+CAPTURE_BONUS*popCount(Nmoves(*pos,j)&pos->PiecesSide[!i]);
	for(i=0;i<2;i++)
		for(j=0;j<64;j++)
			pieceSquare[i][B][j]=MOB_WEIGHT*popCount(Bmoves(*pos,j))+CAPTURE_BONUS*popCount(Bmoves(*pos,j)&pos->PiecesSide[!i]);
	for(i=0;i<2;i++)
		for(j=0;j<64;j++)
			pieceSquare[i][R][j]=MOB_WEIGHT*popCount(Rmoves(*pos,j))+CAPTURE_BONUS*popCount(Rmoves(*pos,j)&pos->PiecesSide[!i]);
	for(i=0;i<2;i++)
		for(j=0;j<64;j++)
			pieceSquare[i][Q][j]=MOB_WEIGHT*popCount(Qmoves(*pos,j))+CAPTURE_BONUS*popCount(Qmoves(*pos,j)&pos->PiecesSide[!i]);

	//Kings
	for(i=0;i<2;i++)
		for(j=0;j<64;j++)
			pieceSquare[i][K][j]=MOB_WEIGHT*popCount(Kmoves(*pos,j));

	//Pawns
	for(i=0;i<64;i++)
	{
		pieceSquare[BLACK][P][i]=/*tempPSQ[i]*/0;
		pieceSquare[WHITE][P][63-i]=pieceSquare[BLACK][P][i];
	}


	/**************KING SAFETY**************/

	//for black
	kingpos=LastOne(pos->PiecesSide[WHITE]&pos->Pieces[K]);
	squares=Kmoves(*pos,kingpos)|toBit[kingpos];
	while(squares)
	{
		target=LastOne(squares);
		//Bishop
		attacks=Bmoves(*pos,target);
		while(attacks)
		{
			target2=LastOne(attacks);
			attacks2=Bmoves(*pos,target2);
			while(attacks2)
			{
				target3=LastOne(attacks2);
				pieceSquare[BLACK][B][target3]+=KS_WEIGHT;
				pieceSquare[BLACK][Q][target3]+=KS_WEIGHT;
				attacks2^=toBit[target3];
			}
			attacks^=toBit[target2];
		}
		attacks=Rmoves(*pos,target);
		while(attacks)
		{
			target2=LastOne(attacks);
			attacks2=Rmoves(*pos,target2);
			while(attacks2)
			{
				target3=LastOne(attacks2);
				pieceSquare[BLACK][R][target3]+=KS_WEIGHT;
				pieceSquare[BLACK][Q][target3]+=KS_WEIGHT;
				attacks2^=toBit[target3];
			}
			attacks^=toBit[target2];
		}
		attacks=Nmoves(*pos,target);
		while(attacks)
		{
			target2=LastOne(attacks);
			attacks2=Nmoves(*pos,target2);
			while(attacks2)
			{
				target3=LastOne(attacks2);
				pieceSquare[BLACK][N][target3]+=KS_WEIGHT;
				attacks2^=toBit[target3];
			}
			attacks^=toBit[target2];
		}
		squares^=toBit[target];
	}

	//for white
	kingpos=LastOne(pos->PiecesSide[BLACK]&pos->Pieces[K]);
	squares=Kmoves(*pos,kingpos)|toBit[kingpos];

	while(squares)
	{
		target=LastOne(squares);
		//Bishop
		attacks=Bmoves(*pos,target);
		while(attacks)
		{
			target2=LastOne(attacks);
			attacks2=Bmoves(*pos,target2);
			while(attacks2)
			{
				target3=LastOne(attacks2);
				pieceSquare[WHITE][B][target3]+=KS_WEIGHT;
				pieceSquare[WHITE][Q][target3]+=KS_WEIGHT;
				attacks2^=toBit[target3];
			}
			attacks^=toBit[target2];
		}
		attacks=Rmoves(*pos,target);
		while(attacks)
		{
			target2=LastOne(attacks);
			attacks2=Rmoves(*pos,target2);
			while(attacks2)
			{
				target3=LastOne(attacks2);
				pieceSquare[WHITE][R][target3]+=KS_WEIGHT;
				pieceSquare[WHITE][Q][target3]+=KS_WEIGHT;
				attacks2^=toBit[target3];
			}
			attacks^=toBit[target2];
		}
		attacks=Nmoves(*pos,target);
		while(attacks)
		{
			target2=LastOne(attacks);
			attacks2=Nmoves(*pos,target2);
			while(attacks2)
			{
				target3=LastOne(attacks2);
				pieceSquare[WHITE][N][target3]+=KS_WEIGHT;
				attacks2^=toBit[target3];
			}
			attacks^=toBit[target2];
		}
		squares^=toBit[target];
	}
}
